\section{Backend Multithreaded}

\indent Tratamos de modificar lo mínimo indispensable en el código provisto para 
transformar el backend\_mono enun backend\_multi. En el código comentamos cada 
uno de los cambios que hicimos para facilitar la correción. Acá hacemos una 
descripción de las modificaciones realizadas.

\indent Para atender las conexiones al servidor tenemos 2 arreglos,
\texttt{socketfd\_cliente} y \texttt{threads}, ambos de tamaño
\texttt{CONEXIONES\_MAXIMAS}. El arreglo \texttt{socketfd\_cliente} va a guardar
el socket (un numero entero) por el cual nos comunicamos con el cliente. El
arreglo \texttt{threads} lo usamos para guardar las estructuras del tipo
$pthread\_t$ correspondientes a cada thread. Es importante destacar que nuestra
implementación no reutiliza los espacios vacíos que dejan en el arreglo
\texttt{threads} los threads que dejan el juego, por lo que como máximo vamos a
aceptar \texttt{CONEXIONES\_MAXIMAS} en total, sin importar si siguen jugando o
si dejaron el juego. Habría que implementar una cola circular, pero el requerimiento 
excede el alance de este trabajo y lo dejamos para una próxima versión.

\indent Cuando un jugador se desconecta, se llama a la función
$terminar\_servidor\_de\_jugador$ la cual se ocupa de cerrar el socket del
jugador correspondiente, quitar las letras que tenía en el
\texttt{tablero\_letras} y por último hace un $pthread\_exit(NULL)$ para
terminar con el thread. Es importante destacar que cuando un jugador se va, no
se borran sus letras del \texttt{tablero\_palabras} que por ende siguen siendo
palabras válidas para los jugadores que siguen jugando.

\indent Al cerrarse el backend, se procede a hacer un $clear$ de cada uno de
los vectores de la matriz \texttt{tablero\_letras\_rwl} y luego a
borrar el \texttt{tablero\_palabras\_rwl}. Por último cerramos el socket del
servidor mediante la función \textit{close}. \\
\\
\indent Los distintos threads que atienden a los clientes acceden a 2 variables
compartidas. Estas varibales son las siguientes:

\begin{itemize}
  \item Tablero de palabras.
  \item Tablero de letras.
\end{itemize}

\indent No fue necesario proteger las variables de ancho y alto del tablero, ya
que se inicializan al crear el backend y luego no se vuelven a escribir.

\indent Para proteger el tablero de letras utilizamos un arreglo de read write
locks(\texttt{tablero\_letras\_rwl}) que tiene las mismas dimensiones que dicho
tablero. De esta manera, se puede proteger a cada letra por separado utilizando
el read write lock presente en la misma posición, pero en el otro arreglo. Esta
decisión fue tomada para permitir que dos jugadores puedan escribir una letra
simultáneamente en distintas posiciones del tablero, lo que mejora la
concurrencia del sistema.

\indent Para proteger el tablero de palabras solamente utilizamos un read write
lock(\texttt{tablero\_palabras\_rwl}). De esta forma, se garantiza que en cada
lectura se obtiene un tablero consistente y en cada escritura se prohibe la
lectura del mismo. Además, se permiten lecturas simultáneas del tablero, ya que
de caso contrario habría una limitación innecesaria y disminuiría la
concurrencia.

\vspace{.4cm}
A continuación detallamos cómo se realizaron las protecciones de las variables
en cada acción posible utilizando las estructuras anteriormente mencionadas.

El tablero de palabras puede ser accedido en alguno de los siguientes casos:

\begin{itemize}
  \item Cuando un usuario pide una actualización: se utiliza un único read lock
sobre todo el tablero, para asegurarse de que el tablero obtenido sea
consistente y permitir que otros jugadores también puedan actualizar sus
tableros en simultáneo. Si no se prohibiera la escritura, podría suceder que al
realizar la actualización, un jugador reciba un tablero que tiene una palabra a
medio escribir y eso rompe la consistencia del tablero de palabras. Cuando se
termina de leer el tablero se utiliza un read unlock.
  \item Cuando un usuario envía su palabra: En este caso utilizamos un write
lock, también sobre todo el tablero. Si bien se podría permitir la escritura en
simultáneo, ya que lo único que se hace es copiar desde el tablero de letras
(que está protegido), lo que se debe bloquear es la lectura del tablero para
evitar que ante una actualización se envíe un tablero con una palabra
incompleta. Una vez que se terminó de escribir la palabra se utiliza un write
unlock para liberar el acceso.
  \item Cuando un jugador escribe una letra: Para fijarse si la letra se está
poniendo en una posición válida cuando un jugador está dejando espacios entre
las letras de la palabra que está escribiendo, el backend lee las posiciones del
tablero de palabras que completarían la palabra que se quiere escribir. Si
dichas posiciones están ocupadas la palabra es válida y si no, no. Si alguien
estuviera escribiendo el tablero en ese momento, podría pasar que depende quien
llegue primero la palabra sea válida o no. Pero esto no es un problema ya que
siempre que se diga que sí, la palabra será válida y si se obtiene un no, no se
podrá escribir la letra. En ambos casos los tableros siguen siendo consistentes
y tiene sentido pensar que un jugador pueda agregar su letra si el otro ya puso
la suya. Por lo tanto, no se realizó ninguna protección en este caso.
\end{itemize}

El tablero de letras puede ser accedido en alguno de los siguientes casos:

\begin{itemize}
  \item Cuando un jugador quiere escribir una letra: Se protege sólo la letra
que será accedida utilizando un write lock de su read write lock
correspondiente. En este caso se protegen dos accesos, primero cuando se lee el
casillero para ver si la ficha es válida y luego, si la ficha es válida, cuando
se escribe. Es fundamental que se prohiba el acceso de todo el bloque, ya que si
se bloqueara el primer acceso, se liberara y luego se bloqueara de nuevo, podría
suceder que al liberarse, la ficha deje de ser válida y por lo tanto se esté
pisando la ficha de otro jugador. Al usar un read write lock distinto para cada
posición del tablero, permitmos que dos jugadores puedan agregar una letra
simultáneamente en distintas posiciones. El hecho de que se pueda acceder leer
casillero en simultáneo puede servir cuando varios jugadores quieren poner la
ficha en una posición que está ocupada, de forma que no tienen que esperar para
obtener su respuesta negativa. Una vez que se terminó de acceder a las variables
se 
libera el acceso llamando a write unlock. Esto se hace tanto si la ficha fue
válida como si no lo fue. 
  \item Cuando un jugador coloca mal una letra o se pierde su conexión y es
necesario quitar su palabra actual: En este caso se utiliza un write lock del
read write lock correspondiente a posición del tablero que se libere. Si bien
aunque no se protegiera tampoco existiría el problema de poder generar tableros
inconsistentes, decidimos proteger esta acción principalmente para lograr que si
un jugador quiere escribir una letra que se está liberando en ese momento, pueda
hacerlo y no reciba como resultado que el casillero está ocupado. Poner este
lock fue más una decisión de implementación que una necesidad. Nuevamente al
tener un read write lock distinto para cada letra que se saca se permite la
concurrencia simultánea para distintas posiciones.
\end{itemize}

\indent Para probar las modificaciones, colocamos algunos $sleep$ en las zonas críticas 
y tratamos de simular la concurrencia a mano. Descubrimos que no podíamos esperar más 
de 3 segundos y suponemos que hay algún tipo de timeout en el frontend. 
El backend\_multi se comportó como esperábamos pero el frontend no, por lo que tuvimos que 
mirar con atención el log para contrastar los resultados.
como esperábamos